package com.hulman.oms.web;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.hulman.oms.bean.DeviceSystem;
import com.hulman.oms.bean.Result;
import com.hulman.oms.bean.Location;
import com.hulman.oms.bean.Tunnel;
import com.hulman.oms.service.DeviceService;
import com.hulman.oms.service.DeviceSystemService;
import com.hulman.oms.service.LocationService;
import com.hulman.oms.service.TunnelService;
import com.hulman.oms.util.NumberUtil;
import com.hulman.oms.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: maxwellens
 */
@RestController
public class LocationController
{
    @Autowired
    private LocationService locationService;
    @Autowired
    private TunnelService tunnelService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private DeviceSystemService deviceSystemService;
    @Autowired
    private HttpServletResponse response;

    @GetMapping("/locations/{id}")
    public Result findLocationById(@PathVariable Integer id)
    {
        Location location = locationService.findLocationById(id);
        return new Result(location);
    }

    @GetMapping("/locations/code/{code}")
    public Result findLocationById(@PathVariable String code)
    {
        Location location = locationService.findLocationByCode(code);
        return new Result(location);
    }

    @GetMapping("/locations")
    public Result findLocations(Integer page, Integer limit, Integer tunnelId, String name)
    {
        Map<String, Object> map = new HashMap<>();
        map.put("page", page);
        map.put("limit", limit);
        map.put("tunnelId", tunnelId);
        map.put("name", name);
        return locationService.findLocationsResult(map);
    }

    @GetMapping("/locations/{locationId}/devices")
    public Result findLocationDevices(@PathVariable Integer locationId)
    {
        Map<String, Object> map = new HashMap<>();
        map.put("locationId", locationId);
        return deviceService.findDevicesResult(map);
    }

    @GetMapping("/tunnels/locations")
    public Result findTunnelLocations(String tunnelIds)
    {
        List<Object> data = new LinkedList<>();
        List<Tunnel> tunnels;
        if (StringUtil.isEmpty(tunnelIds))
        {
            tunnels = tunnelService.findAllTunnels();
        } else
        {
            tunnels = tunnelService.findTunnelsByIds(NumberUtil.parseIntArray(tunnelIds));
        }

        for (Tunnel tunnel : tunnels)
        {
            Map<String, Object> tunnelItem = new LinkedHashMap<>();
            tunnelItem.put("id", tunnel.getId());
            tunnelItem.put("name", tunnel.getName());
            List<Location> locations = locationService.findLocationsByTunnelId(tunnel.getId());
            List<Object> areas = locations.stream().map(item ->
            {
                Map<String, Object> areaItem = new LinkedHashMap<>();
                areaItem.put("id", item.getId());
                areaItem.put("name", item.getAbbr());
                return areaItem;
            }).collect(Collectors.toList());
            tunnelItem.put("areas", areas);
            data.add(tunnelItem);
        }
        return new Result(data);
    }

    @GetMapping("/tunnels/systems")
    public Result findTunnelSystems(String tunnelIds)
    {
        List<Object> data = new LinkedList<>();
        List<Tunnel> tunnels;
        List<DeviceSystem> systemList = deviceSystemService.findDeviceSystems();
        if (StringUtil.isEmpty(tunnelIds))
        {
            tunnels = tunnelService.findAllTunnels();
        } else
        {
            tunnels = tunnelService.findTunnelsByIds(NumberUtil.parseIntArray(tunnelIds));
        }
        for (Tunnel tunnel : tunnels)
        {
            Map<String, Object> tunnelItem = new LinkedHashMap<>();
            tunnelItem.put("id", tunnel.getId());
            tunnelItem.put("name", tunnel.getName());
            List<Object> systems = systemList.stream().map(item ->
            {
                Map<String, Object> systemItem = new LinkedHashMap<>();
                systemItem.put("id", tunnel.getId() * 100 + item.getId());
                systemItem.put("name", item.getName());
                return systemItem;
            }).collect(Collectors.toList());
            tunnelItem.put("systems", systems);
            data.add(tunnelItem);
        }
        return new Result(data);
    }

    @DeleteMapping("/locations/{ids}")
    public Result deleteLocationById(@PathVariable String ids)
    {
        int[] idArrays = NumberUtil.parseIntArray(ids);
        for (Integer id : idArrays)
        {
            locationService.deleteLocationById(id);
        }
        return Result.SUCCESS;
    }

    @PutMapping("/locations")
    public Result saveLocation(Location location)
    {
        locationService.saveLocation(location);
        return Result.SUCCESS;
    }

    @RequestMapping("/locations/index")
    public Result findLocationsIndex(String name, String tunnelIds)
    {
        Map<String, Object> condition = new HashMap<>();
        condition.put("name", name);
        if (! StringUtil.isEmpty(tunnelIds))
        {
            condition.put("tunnelIds", tunnelIds.split(","));
        }
        List<Location> locations = locationService.findLocations(condition);
        Map<String, List<String>> map = new HashMap<>();
        for (Location location : locations)
        {
            String letter = StringUtil.getPinyinFirstLetters(location.getName().substring(0, 1));
            if (! map.containsKey(letter))
            {
                map.put(letter, new ArrayList<>());
            }
            map.get(letter).add(location.getName());
        }
        //对字母进行排序
        Object[] keys = map.keySet().toArray();
        Arrays.sort(keys);
        List<Object> result = new ArrayList<>();
        for (Object key : keys)
        {
            Map<String, Object> item = new HashMap<>();
            item.put("letter", key);
            item.put("data", map.get(key));
            result.add(item);
        }
        return new Result(result);
    }

    @PostMapping("/locations/import")
    public Result importLocations(MultipartFile file) throws IOException
    {
        File tmp = new File(System.getProperty("java.io.tmpdir") + "/" + System.currentTimeMillis() + ".xlsx");
        file.transferTo(tmp);
        List<Location> locations = EasyExcel.read(tmp).head(Location.class).sheet(0).doReadSync();
        locationService.importLocations(locations);
        return Result.SUCCESS;
    }

    @GetMapping("/locations/export")
    public void exportLocations(String name, Integer tunnelId) throws IOException
    {
        response.setContentType("multipart/form-data");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=location.xlsx");

        Map<String, Object> map = new HashMap<>();
        map.put("name", name);
        map.put("tunnelId", tunnelId);

        List<Location> locations = locationService.findLocations(map);
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
        WriteSheet sheet = EasyExcel.writerSheet(0, "位置").head(Location.class).build();
        excelWriter.write(locations, sheet);
        excelWriter.finish();
    }

}
